#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
数据模型定义
包含用户、样本、日志等数据类
"""

from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from typing import Optional, Dict, List, Any

class UserRole(Enum):
    """用户角色枚举"""
    ADMIN = "管理员"
    VIEWER = "查看员"

class SampleStatus(Enum):
    """样本状态枚举"""
    PENDING = "待处理"
    PROCESSED = "已处理"
    EXPORTED = "已导出"
    SENT = "已发送"

class CommunicationType(Enum):
    """通信类型枚举"""
    SERIAL = "串口"
    TCP = "TCP"

class ProtocolType(Enum):
    """协议类型枚举"""
    CUSTOM = "自有协议"
    HL7 = "HL7协议"

class AnalysisMode(Enum):
    """分析模式枚举"""
    NORMAL = "常规模式"
    VARIANT = "变异模式"
    THALASSEMIA = "地贫模式"
    FAST_VARIANT = "快速变异模式"

class EncryptionType(Enum):
    """加密类型枚举"""
    NONE = "None"
    AES = "AES"

@dataclass
class User:
    """用户数据类"""
    id: int
    username: str
    password_hash: str
    role: UserRole
    created_time: datetime
    last_login: Optional[datetime] = None

@dataclass
class SampleInfo:
    """样本信息数据类"""
    sample_id: str = ""
    sample_number: str = ""
    sample_uid: str = ""  # 仪器检测编号，对应数据库lis_samples表的sample_uid字段
    patient_name: str = ""
    patient_age: int = 0
    patient_gender: str = ""
    datetime: str = ""
    sample_type: str = ""
    sample_type_name: str = ""
    sample_category: str = ""
    report_id: str = ""
    position: str = ""  # 样本在仪器上的位置编号

@dataclass
class TestResult:
    """检测结果数据类"""
    test_name: str
    value: str  # 保持原始字符串格式，不丢失前导0或小数位
    unit: str = ""
    reference_range: str = ""
    is_abnormal: bool = False
    warning_color: str = "red"

@dataclass
class Results:
    """检测结果集合数据类"""
    # 基础数值字段
    HbA1a: str = ""
    HbA1b: str = ""
    HbF: str = ""
    LA1c: str = ""  # 修正字段名
    HbA1c: str = ""
    HbA0: str = ""
    eAG: str = ""
    
    # 变异筛查字段
    A2: str = ""
    HbE: str = ""
    HbD: str = ""
    HbS: str = ""
    HbC: str = ""
    p3: str = ""
    v_win: str = ""
    
    # 数组字段
    TIME: List[str] = field(default_factory=list)
    AREA: List[str] = field(default_factory=list)
    
    # 详情对象
    TIME_DETAILS: Dict[str, Any] = field(default_factory=dict)
    AREA_DETAILS: Dict[str, Any] = field(default_factory=dict)
    
    # 其他结果字段
    other_results: Dict[str, str] = field(default_factory=dict)

@dataclass
class ImageInfo:
    """图片信息数据类"""
    filename: str = ""
    size: int = 0
    path: str = ""
    saved: bool = False
    hex_data: str = ""  # 十六进制数据
    base64_data: str = ""  # Base64数据
    error: str = ""

@dataclass
class ModeInfo:
    """模式信息数据类"""
    name: str = ""  # 模式名称
    description: str = ""  # 模式描述
    mode_name: str = ""
    mode_description: str = ""
    test_count: int = 0
    test_items: List[str] = field(default_factory=list)
    typical_fields: List[str] = field(default_factory=list)  # 典型检测项目列表

@dataclass
class Sample:
    """样本数据类 - 重新设计支持新的数据结构"""
    id: str
    protocol: str = "CUSTOM_LIS"
    machine_model: str = ""
    machine_id: str = ""
    
    # 子对象字段
    sample_info: SampleInfo = field(default_factory=SampleInfo)
    results: Results = field(default_factory=Results)
    image: ImageInfo = field(default_factory=ImageInfo)
    analysis_mode: str = ""
    mode_info: ModeInfo = field(default_factory=ModeInfo)
    
    # 原始数据和接收时间
    raw: str = ""
    receive_time: datetime = field(default_factory=datetime.now)
    
    # 状态和时间戳
    status: SampleStatus = SampleStatus.PENDING
    created_time: datetime = field(default_factory=datetime.now)
    updated_time: datetime = field(default_factory=datetime.now)
    
    def __post_init__(self):
        """初始化后处理"""
        if self.updated_time == self.created_time:
            self.updated_time = datetime.now()
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式，用于JSON序列化"""
        return {
            'id': self.id,
            'protocol': self.protocol,
            'machine_model': self.machine_model,
            'machine_id': self.machine_id,
            'sample_info': {
                'sample_id': self.sample_info.sample_id,
                'sample_number': self.sample_info.sample_number,
                'sample_uid': self.sample_info.sample_uid,  # 仪器检测编号
                'patient_name': self.sample_info.patient_name,
                'patient_age': self.sample_info.patient_age,
                'patient_gender': self.sample_info.patient_gender,
                'datetime': self.sample_info.datetime,
                'sample_type': self.sample_info.sample_type,
                'sample_type_name': self.sample_info.sample_type_name,
                'sample_category': self.sample_info.sample_category,
                'report_id': self.sample_info.report_id,
                'position': self.sample_info.position
            },
            'results': {
                'HbA1a': self.results.HbA1a,
                'HbA1b': self.results.HbA1b,
                'HbF': self.results.HbF,
                'LA1c': self.results.LA1c,
                'HbA1c': self.results.HbA1c,
                'HbA0': self.results.HbA0,
                'eAG': self.results.eAG,
                'A2': self.results.A2,
                'HbE': self.results.HbE,
                'HbD': self.results.HbD,
                'HbS': self.results.HbS,
                'HbC': self.results.HbC,
                'p3': self.results.p3,
                'v_win': self.results.v_win,
                'TIME': self.results.TIME,
                'AREA': self.results.AREA,
                'TIME_DETAILS': self.results.TIME_DETAILS,
                'AREA_DETAILS': self.results.AREA_DETAILS,
                'other_results': self.results.other_results
            },
            'image': {
                'filename': self.image.filename,
                'size': self.image.size,
                'path': self.image.path,
                'saved': self.image.saved,
                'hex_data': self.image.hex_data,
                'base64_data': self.image.base64_data,
                'error': self.image.error
            },
            'analysis_mode': self.analysis_mode,
            'mode_info': {
                'mode_name': self.mode_info.mode_name,
                'mode_description': self.mode_info.mode_description,
                'test_count': self.mode_info.test_count,
                'test_items': self.mode_info.test_items
            },
            'raw': self.raw,
            'receive_time': self.receive_time.isoformat(),
            'status': self.status.value,
            'created_time': self.created_time.isoformat(),
            'updated_time': self.updated_time.isoformat()
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'Sample':
        """从字典创建Sample对象"""
        # 创建子对象
        sample_info = SampleInfo(**data.get('sample_info', {}))
        results = Results(**data.get('results', {}))
        image = ImageInfo(**data.get('image', {}))
        mode_info = ModeInfo(**data.get('mode_info', {}))
        
        # 解析时间字段
        receive_time = datetime.fromisoformat(data.get('receive_time', datetime.now().isoformat()))
        created_time = datetime.fromisoformat(data.get('created_time', datetime.now().isoformat()))
        updated_time = datetime.fromisoformat(data.get('updated_time', datetime.now().isoformat()))
        
        # 解析状态
        status = SampleStatus(data.get('status', 'PENDING'))
        
        return cls(
            id=data['id'],
            protocol=data.get('protocol', 'CUSTOM_LIS'),
            machine_model=data.get('machine_model', ''),
            machine_id=data.get('machine_id', ''),
            sample_info=sample_info,
            results=results,
            image=image,
            analysis_mode=data.get('analysis_mode', ''),
            mode_info=mode_info,
            raw=data.get('raw', ''),
            receive_time=receive_time,
            status=status,
            created_time=created_time,
            updated_time=updated_time
        )

@dataclass
class OperationLog:
    """操作日志数据类"""
    id: int
    operation_time: datetime
    operator: str
    operation_type: str
    operation_content: str
    ip_address: str = ""

@dataclass
class HospitalInfo:
    """医院信息数据类"""
    name: str = ""
    address: str = ""
    contact: str = ""
    logo_path: str = ""

@dataclass
class CommunicationConfig:
    """通信配置数据类"""
    comm_type: CommunicationType
    protocol_type: ProtocolType
    host: str = ""
    port: int = 0
    serial_port: str = ""
    baudrate: int = 9600
    data_bits: int = 8
    stop_bits: int = 1
    parity: str = "N"



@dataclass
class WarningRange:
    """警告区间数据类"""
    test_name: str
    min_value: float
    max_value: float
    unit: str
    warning_color: str = "red"
    created_time: datetime = None 

@dataclass
class BackupConfig:
    """备份配置数据类"""
    auto_backup: bool = True
    auto_backup_interval: int = 24  # 小时
    close_backup: bool = True
    encryption_type: EncryptionType = EncryptionType.AES
    max_backup_files: int = 30
    backup_database: bool = True
    backup_config: bool = True
    backup_logs: bool = True
    backup_path: str = ""

@dataclass
class BackupInfo:
    """备份信息数据类"""
    backup_name: str
    backup_time: datetime
    backup_path: str
    file_size: int
    encryption_type: EncryptionType
    backup_config: BackupConfig
    source_files: Dict[str, str]
    created_time: Optional[datetime] = None
    
    def __post_init__(self):
        """初始化后处理"""
        if self.created_time is None:
            self.created_time = datetime.now() 